package tomcat.Impl;

import tomcat.Cookie;
import tomcat.HttpServletRequest;
import tomcat.HttpSession;

import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;
import java.net.URLDecoder;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

public class HttpServletRequestImpl implements HttpServletRequest {

    private final InputStream in;
    private String method;
    private String requestURI;
    private String protocol;
    // LinkedHashMap ==> 有序的map集合
    private Map<String,String> headerMap = new LinkedHashMap<>();
    private Map<String,String> paramsMap = new LinkedHashMap<>();
    private Socket socket;

    public HttpServletRequestImpl(Socket socket) throws IOException {
        this.socket = socket;
        this.in = socket.getInputStream();
        String line = readLine(in);
        // 解析头行
        String[] items = line.split(" ");
        this.method = items[0];
        this.requestURI = items[1];
        this.protocol = items[2];

        String paramStr = this.requestURI.replaceAll("[^\\?#]+(\\?(.+))?(#.+)?","$2");
        System.out.println(paramStr);
        if (paramStr!=null & paramStr.length()>0){
            items = paramStr.split("&");
            for (String item : items) {
                String[] nameAndValue = item.split("=");
                // 如果有参数编码 汉字 ==> utf-8 ==> 解码
                nameAndValue[0] = URLDecoder.decode(nameAndValue[0],"utf-8");
                nameAndValue[1] = URLDecoder.decode(nameAndValue[1],"utf-8");
                paramsMap.put(nameAndValue[0], nameAndValue[1]);
            }
        }
        // 一直读取，直到遇到一个空行
        while((line = readLine(in)).isEmpty() == false){
            items = line.split(": ");
            headerMap.put(items[0],items[1]);
        }
        

        // TODO body(正文暂时不处理)
        // post 请求参数: method = post, content-type: 表单，文件上传，length
        // 获取正文的长度 Content-Length
        /**
         * Content-Length : 正文的大小
         * 正文内容的类型 application/x-www-form-urlencoded 表单类型
         *              multipart/form-data 文件上传
         * Content-Type: application/x-www-form-urlencoded  => 默认类型
         * Content-Type: multipart/form-data;boundary=----WebKitFormBoundaryfDfIGEvJbQfzkAOA
         *
         * 如果上传文件处理策略
         * 1. 如果没有超过界限，直接处理，保存到内存中，封装成对象 Part.write(本地文件)
         * 2. 如果文件超过界限，将文件保存为临时的磁盘文件，
         * 3. 因此，servlet 对上传文件大小，临时文件边界大小，临时文件存放位置都有设置
         */
        if ("POST".equals(method)){
            String length = headerMap.get("Content-Length");
            int iLength = Integer.valueOf((length));
            byte[] bytes = new byte[iLength];
            int count;
            InputStream in = socket.getInputStream();
            // 一次性读入全部的数据
            in.read(bytes,0,iLength);
            System.out.println(new String(bytes,0,iLength));
        }
    }

    private String readLine(InputStream in) throws IOException {
        StringBuilder line = new StringBuilder();
        char c;
        while(true){
            c = (char) in.read(); // 一次读入一个字符
            // window 系统的换行是 \r回车\n换行
            if(c == '\r'){
                in.read(); // 读掉  \n
                System.out.println(line);
                return line.toString();
            } else {
                line.append(c);
            }
        }
    }

    @Override
    public InputStream getInputStream() {

        return null;
    }

    @Override
    public String getMethod() {
        return method;
    }

    @Override
    public String getRequestURI() {

        return requestURI;
    }

    @Override
    public String getProtocol() {
        return protocol;
    }

    @Override
    public String getHeader(String name) {

        return headerMap.get(name);
    }

    @Override
    public Cookie[] getCookies() {
        String cookies = headerMap.get("Cookie");
        // 加入空值判断，避免第一次访问无cookie数据导致的空指针异常
        if (cookies==null){
            return null;
        }
        String[] splits = cookies.split(";\\s");
        Cookie[] cookieObjs = new Cookie[splits.length];
        for (int i = 0; i < splits.length; i++) {
            String split = splits[i];
            String[] nameAndValues = split.split("=");
            // 如果有 非西方字符，请解码
            cookieObjs[i] = new CookieImpl(nameAndValues[0],nameAndValues[1]);
        }
        return cookieObjs;
    }

    @Override
    public String getRequestedSessionId() {
        return null;
    }

    // 会话容器
    private static Map<String,HttpSession> sessionMap = new HashMap<>();
    @Override
    public HttpSession getSession() {
        /**
         * 容器没有回话对象的情况:
         * 1、第一次访问网址
         * 2、会话超时，30分钟
         * 3、手动执行 invalidate 手动超时
         * 4、会话机制被打破
         *      1)cookie 存放会话id 默认
         *          1、将会话id 发送到浏览器，JSESSIONID = xxxxx
         *          2、从cookie获取会话id，提取会话对象
         *      2) 地址 保存会话id
         *      3) 隐藏域 保存会话id
         */

        // 从cookie中查找会话id
        Cookie[] cookies = this.getCookies();
        String sessionId = null;
        if (cookies != null){
            for (Cookie cookie : cookies) {
                if (cookie.getName().equals("JSESSIONID")){
                    sessionId = cookie.getValue();
                    break;
                }
            }
        }
        HttpSession httpSession = sessionMap.get("????");
        // 如果会话容器中没有浏览器的会话对象
        if (httpSession == null){
            // 那么就为其创建一个
            httpSession = new HttpSessionImpl();
            sessionMap.put(httpSession.getId(),httpSession);
        }
        return httpSession;
    }

    @Override
    public String getParameter(String name) {
        return paramsMap.get(name);
    }

    @Override
    public String[] getParameterValues(String name) {
        return new String[0];
    }

    @Override
    public String getQueryString() {
        return null;
    }

    @Override
    public void getSession(HttpSession session) {

    }
}
